﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.ComponentModel;

namespace Kokomo.Mirror.PeFormat
{
	[Description("Optional Header (32-bit)")]
	public class OptionalHeader32 : PeHeaderStruct, IOptionalHeader
	{
		public static readonly int StructSize = 0xE0;

		//
		// Standard fields.
		//

		[TypeConverter(typeof(HexConverter))]
		public ushort Magic { get; private set; }

		[DisplayName("Linker version")]
		public SmallVersion LinkerVersion { get; private set; }

		[DisplayName("Size of code")]
		[PeCategory(PeCategory.Layout)]
		[TypeConverter(typeof(HexConverter))]
		public uint SizeOfCode { get; private set; }

		[DisplayName("Size of initialized data")]
		[PeCategory(PeCategory.Layout)]
		[TypeConverter(typeof(HexConverter))]
		public uint SizeOfInitializedData { get; private set; }

		[DisplayName("Size of uninitialized data")]
		[PeCategory(PeCategory.Layout)]
		[TypeConverter(typeof(HexConverter))]
		public uint SizeOfUninitializedData { get; private set; }

		[DisplayName("Address of entry point")]
		[PeCategory(PeCategory.Layout)]
		[TypeConverter(typeof(HexConverter))]
		public uint AddressOfEntryPoint { get; private set; }

		[DisplayName("Base of code")]
		[PeCategory(PeCategory.Layout)]
		[TypeConverter(typeof(HexConverter))]
		public uint BaseOfCode { get; private set; }

		[DisplayName("Base of data")]
		[PeCategory(PeCategory.Layout)]
		[TypeConverter(typeof(HexConverter))]
		public uint BaseOfData { get; private set; }

		//
		// NT additional fields.
		//

		[DisplayName("Image base")]
		[PeCategory(PeCategory.Layout)]
		[TypeConverter(typeof(HexConverter))]
		public uint ImageBase { get; private set; }

		[DisplayName("Section alignment")]
		[PeCategory(PeCategory.Layout)]
		[TypeConverter(typeof(HexConverter))]
		public uint SectionAlignment { get; private set; }

		[DisplayName("File alignment")]
		[PeCategory(PeCategory.Layout)]
		[TypeConverter(typeof(HexConverter))]
		public uint FileAlignment { get; private set; }

		[DisplayName("Operating system version")]
		[PeCategory(PeCategory.Platform)]
		public Version OperatingSystemVersion { get; private set; }

		[DisplayName("Image version")]
		public Version ImageVersion { get; private set; }

		[DisplayName("Subsystem version")]
		[PeCategory(PeCategory.Platform)]
		public Version SubsystemVersion { get; private set; }

		[DisplayName("Win32 version value")]
		[PeCategory(PeCategory.Platform)]
		[TypeConverter(typeof(HexConverter))]
		public uint Win32VersionValue { get; private set; }

		[DisplayName("Size of image")]
		[PeCategory(PeCategory.Layout)]
		[TypeConverter(typeof(HexConverter))]
		public uint SizeOfImage { get; set; }

		[DisplayName("Size of headers")]
		[PeCategory(PeCategory.Layout)]
		[TypeConverter(typeof(HexConverter))]
		public uint SizeOfHeaders { get; set; }

		[DisplayName("Checksum")]
		[TypeConverter(typeof(HexConverter))]
		public uint CheckSum { get; private set; }

		[DisplayName("Subsystem")]
		[PeCategory(PeCategory.Platform)]
		public Subsystem Subsystem { get; private set; }

		[DisplayName("DLL characteristics")]
		public DllCharacteristics DllCharacteristics { get; private set; }

		[DisplayName("Size of stack reserve")]
		[PeCategory(PeCategory.Memory)]
		[TypeConverter(typeof(HexConverter))]
		public uint SizeOfStackReserve { get; private set; }

		[DisplayName("Size of stack commit")]
		[PeCategory(PeCategory.Memory)]
		[TypeConverter(typeof(HexConverter))]
		public uint SizeOfStackCommit { get; private set; }

		[DisplayName("Size of heap reserve")]
		[PeCategory(PeCategory.Memory)]
		[TypeConverter(typeof(HexConverter))]
		public uint SizeOfHeapReserve { get; private set; }

		[DisplayName("Size of heap commit")]
		[PeCategory(PeCategory.Memory)]
		[TypeConverter(typeof(HexConverter))]
		public uint SizeOfHeapCommit { get; private set; }

		[DisplayName("Loader flags")]
		[TypeConverter(typeof(HexConverter))]
		public uint LoaderFlags { get; private set; }

		[DisplayName("Number of RVAs and sizes")]
		[PeCategory(PeCategory.Layout)]
		public uint NumberOfRvaAndSizes { get; private set; }

		[Browsable(false)]
		[SerializedArray(ArrayLengthEncoding.Fixed, 16)]
		public DataDirectoryEntry[] DataDirectory { get; private set; }

		[NonSerializedProperty]
		long IOptionalHeader.ImageBase
		{
			get { return this.ImageBase; }
		}

		[NonSerializedProperty]
		long IOptionalHeader.SizeOfStackReserve
		{
			get { return this.SizeOfStackReserve; }
		}

		[NonSerializedProperty]
		long IOptionalHeader.SizeOfStackCommit
		{
			get { return this.SizeOfStackCommit; }
		}

		[NonSerializedProperty]
		long IOptionalHeader.SizeOfHeapReserve
		{
			get { return this.SizeOfHeapReserve; }
		}

		[NonSerializedProperty]
		long IOptionalHeader.SizeOfHeapCommit
		{
			get { return this.SizeOfHeapCommit; }
		}
	}
}
